using System;
using System.IO;
using SQLRunnerLib.Project;
using SQLRunnerLib.Services;
using SQLServices.Log;

namespace SQLRunnerLib.Util
{
	public enum SessionLogLevel
	{
		info,
		error,
		none
	}

	[Flags]
	public enum ErrorIndicator:int
	{
		none = 0,
		AppFailure = 1,
		StopExecution = 2
	}

	/// <summary>
	/// Reads the command line arguments and start the application 
	/// command line arguments
	/// -p:[project file path]		Indicates the project file to use
	/// -s:[server name]			SQL Server instance
	/// -d:[database name]			Database
	/// -t							Trusted connection, default value is TRUE
	/// -u:[user name]
	/// -w:[password]
	/// </summary>
	public class LineParser
	{
		private bool _isProjectAvailable = false;
		private bool _isTrustedConnection = false;
		private string _serverName = string.Empty;
		private string _databaseName = string.Empty;
		private string _userName = string.Empty;
		private string _pwd = string.Empty;
		private bool _showHelp = false;
		private SessionLogLevel _logLevel = SessionLogLevel.error;
		private ErrorIndicator _errorIndicator = ErrorIndicator.none;

		private SQLProject _proj;
		private string[] _options = new string[] {"p:", "s:", "d:", "u:", "w:", "e:", "h", "t"};

		public LineParser(string[] args)
		{
			foreach (string arg in args) {
				string value = string.Empty;
				if (arg.StartsWith("-"))
					value = arg.Substring(1).ToLower();
				else
					continue;

				foreach (string option in _options) {
					if (value.StartsWith(option)) {
						value = value.Substring(option.Length);
						updateFlags(option, value);
						break;
					}
				}
			}
		}

		public bool IsProjectAvailable {
			get { return _isProjectAvailable; }
		}

		public SQLProject Project 
		{
			get { return _proj; }
		}

		public bool IsTrustedConnection {
			
			get {
				// check if trusted connection was setup in the command line flags
				if (_isTrustedConnection) return true;
				// If server name or user name is empty we force a trusted connection
				return !(_serverName.Length > 0 && _userName.Length > 0);
			}
		}

		public string ServerName {
			get { return _serverName; }
		}

		public string UserName {
			get { return _userName; }
		}

		public string Pwd {
			get { return _pwd; }
		}

		public SessionLogLevel LogLevel {
			get { return _logLevel; }
		}

		public string DatabaseName {
			get { return _databaseName; }
		}

		public bool ShowHelp {
			get { return _showHelp; }
		}

		public ErrorIndicator ErrorLevel {
			get { return _errorIndicator; }
		}	

		private void updateFlags(string option, string value) {
			switch (option) {
				case "p:":
					doProject(value);
					break;
				case "s:":
					_serverName = value;
					break;
				case "d:":
					_databaseName = value;
					break;
				case "t":
					_isTrustedConnection = true;
					break;
				case "u:":
					_userName = value;
					break;
				case "w:":
					_pwd = value;
					break;
				case "h":
					_showHelp = true;
					break;
				case "e:":
					doError(value);
					break;
				default:
					ServiceContainer.Logger.LogMessage(string.Format(
						"The {0} option is invalid", option), MsgLevel.Error);
					throw new ApplicationException(string.Format(
						"The {0} option is invalid", option));
			}
		}

		private void doProject(string value) {
			value = value.Replace("'", string.Empty).Replace("\"",string.Empty);
			FileInfo projFile = new FileInfo(value);
			if (!projFile.Exists) {
				string msg = string.Format("Project file [{0}] does not exists", value);
				ServiceContainer.Logger.LogMessage(msg, MsgLevel.Error);
				return;
			}
			try {
				_proj = SQLProject.Deserialize(value);
				_isProjectAvailable = true;
			}
			catch {
				string msg = string.Format("Project file [{0}] could not be read", value);
				ServiceContainer.Logger.LogMessage(msg, MsgLevel.Error);
			}
		}

		private void doError(string value) {
			ErrorIndicator errorvalue = ErrorIndicator.none;
			try {
				int error = int.Parse(value);
				if ( ( error & (int) ErrorIndicator.AppFailure) == (int) ErrorIndicator.AppFailure) {
					errorvalue = ErrorIndicator.AppFailure;
				}
				if ( ( error & (int) ErrorIndicator.StopExecution) == (int) ErrorIndicator.StopExecution) {
					errorvalue |= ErrorIndicator.StopExecution;
				}
			}
			catch (Exception ex) {
				ServiceContainer.Logger.LogMessage("Error parsing error level: " + ex.Message, MsgLevel.Error);
			}
			_errorIndicator = errorvalue;

		}
	}
}
